#ifndef SERVER_H
#define SERVER_H

#include <QTcpServer>
#include <QTcpSocket>

#include <QGraphicsView>
#include <QTimer>
#include <QMutex>

#include "urg/UrgCtrl.h"
#include "urg/RangeSensorParameter.h"

#include "sensor/Laser.h"
#include "sensor/Camera.h"

#include "sensor/MJPEGClient.h"
#include "sensor/RS232Motor.h"

#include "qdisplay/QwImageViewer.h"
#include "qdisplay/QiLaserScan.h"
#include "qdisplay/QwController.h"

using namespace qrk;

class MotorThread;
class URGThread;
class TCPDataThread;

class Server : public QTcpServer
{
    Q_OBJECT

public:    
    Server();
    ~Server();

    void run();
    void display();

    int	m_speedL;
    int m_speedR;

    CameraData m_camera;
    LaserData m_laser;

public:
    enum SensorType { SENSOR_LASER, SENSOR_CAMERA, SENSOR_ROBOT };

signals:
    void dataLaserReady( LaserData* laser );

public slots:
    void gotNewCommand( int cmd_left, int cmd_right );
    void gotNewSensorData( const QImage* pic );
    void gotNewSensorData( const RS232Data* sensorL, const RS232Data* sensorR );
    void gotNewSensorData( vector<long> laserdata, const RangeSensorParameter& urg_params );


protected:
    virtual void incomingConnection( int descriptor );

private:  
    void initThreadLaser();

    void runThreadVideo();
    void runThreadMotor();
    void runThreadLaser();
    void runThreadTCPData();

    void displayLaser();
    void displayCamera();
    void displayController();

    MJPEGClient* m_mjpegThread;
    MotorThread* m_motorThread;
    URGThread* m_laserThread;

    QwImageViewer* m_cameraViewer;
    QiLaserScan* m_laserViewer;
    QwController* m_controllerViewer;

    QGraphicsScene* m_scene;
    QGraphicsView* m_view;

    QMutex m_mutex;

};

class MotorThread : public QThread
{

public:
    MotorThread( Server* server );

    void init();
    void run();
    void stop();

private:
    Server* m_server;

    RS232Motor m_controller;
    RS232Data m_dataL;
    RS232Data m_dataR;
    int m_hCOM;
};


class URGThread : public QThread
{

public:
    URGThread( Server* server );

    void init();
    void run();
    void stop();

private:
    Server* m_server;

    UrgCtrl m_urg;
    RangeSensorParameter m_urg_params;
};

class TCPDataThread : public QThread
{
    Q_OBJECT

public:
    TCPDataThread( int descriptor );

    void run();
    void stop();

signals:
    void commandReceived( int cmd_left, int cmd_right );

public slots:
    void dataLaserToSend( LaserData* laser );
    void dataToRead();

private:
    QTcpSocket m_socket;
};

unsigned long int getCurrentTime();


#endif // SERVER_H
